package com.sy.simpleegg.util

import android.app.Activity
import android.app.Application.ActivityLifecycleCallbacks
import android.content.Context
import android.content.res.Resources
import android.os.Build
import android.os.Bundle
import android.os.LocaleList
import android.text.TextUtils
import androidx.core.os.ConfigurationCompat
import androidx.core.os.LocaleListCompat
import com.sy.simpleegg.constant.Constant
import java.util.Locale

object MultiLanguageUtils {
    /**
     * 修改应用内语言设置
     * @param language  语言
     * @param area      地区
     */
    fun changeLanguage(context: Context, language: String?, area: String?): Boolean {
        if (TextUtils.isEmpty(language) && TextUtils.isEmpty(area)) {
            //如果语言和地区都是空，那么跟随系统
            var language: String by Preference(Constant.SETTING_LANGUAGE, "")
            var area: String by Preference(Constant.SETTING_LANGUAGE_AREA, "")
            language = ""
            area = ""
            return false
        } else {
            val spLanguage: String by Preference(Constant.SETTING_LANGUAGE, "")
            val spCountry: String by Preference(Constant.SETTING_LANGUAGE_AREA, "")
            if (spLanguage == language && spCountry == area){
                return false
            }
            //不为空，修改app语言，持久化语言选项信息
            val newLocale = Locale(language, area)
            setAppLanguage(context, newLocale)
            saveLanguageSetting(context, newLocale)
            return true
        }
    }

    /**
     * 更新应用语言（核心）
     * @param context
     * @param locale
     */
    private fun setAppLanguage(context: Context, locale: Locale) {
        val resources = context.resources
        val metrics = resources.displayMetrics
        val configuration = resources.configuration
        //Android 7.0以上的方法
        if (Build.VERSION.SDK_INT >= 24) {
            configuration.setLocale(locale)
            configuration.setLocales(LocaleList(locale))
            context.createConfigurationContext(configuration)
            //实测，updateConfiguration这个方法虽然很多博主说是版本不适用
            //但是我的生产环境androidX+Android Q环境下，必须加上这一句，才可以通过重启App来切换语言
            resources.updateConfiguration(configuration, metrics)
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            //Android 4.1 以上方法
            configuration.setLocale(locale)
            resources.updateConfiguration(configuration, metrics)
        } else {
            configuration.locale = locale
            resources.updateConfiguration(configuration, metrics)
        }
    }

    /**
     * 跟随系统语言
     */
    fun attachBaseContext(context: Context): Context {
        val spLanguage: String by Preference(Constant.SETTING_LANGUAGE, "")
        val spCountry: String by Preference(Constant.SETTING_LANGUAGE_AREA, "")
        if (!TextUtils.isEmpty(spLanguage) && !TextUtils.isEmpty(spCountry)) {
            val locale = Locale(spLanguage, spCountry)
            setAppLanguage(context, locale)
        }
        return context
    }

    /**
     * 判断SharedPrefences中存储和app中的多语言信息是否相同
     */
    fun isSameWithSetting(context: Context): Boolean {
        val locale = getAppLocale(context)
        val language = locale.language
        val country = locale.country
        val sp_language: String by Preference(Constant.SETTING_LANGUAGE, "")
        val sp_country: String by Preference(Constant.SETTING_LANGUAGE_AREA, "")
        return if (language == sp_language && country == sp_country) {
            true
        } else {
            false
        }
    }

    /**
     * 保存多语言信息到sp中
     */
    fun saveLanguageSetting(context: Context?, locale: Locale) {
        var language: String by Preference(Constant.SETTING_LANGUAGE, "")
        var area: String by Preference(Constant.SETTING_LANGUAGE_AREA, "")
        language = locale.language
        area = locale.country
    }

    /**
     * 获取应用语言
     */
    fun getAppLocale(context: Context): Locale {
        val local: Locale
        local = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            context.resources.configuration.locales[0]
        } else {
            context.resources.configuration.locale
        }
        return local
    }

    val systemLanguage: LocaleListCompat
        /**
         * 获取系统语言
         */
        get() {
            val configuration =
                Resources.getSystem().configuration
            return ConfigurationCompat.getLocales(configuration)
        }

    //在Application实现类注册Activity生命周期监听回调，有些版本不加的话多语言切换不回来
    //registerActivityLifecycleCallbacks(callbacks);
    var callbacks: ActivityLifecycleCallbacks = object : ActivityLifecycleCallbacks {
        override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
            val language: String by Preference(Constant.SETTING_LANGUAGE, "")
            val country: String by Preference(Constant.SETTING_LANGUAGE_AREA, "")
            if (!TextUtils.isEmpty(language) && !TextUtils.isEmpty(country)) {
                //强制修改应用语言
                if (!isSameWithSetting(activity)) {
                    val locale = Locale(language, country)
                    setAppLanguage(activity, locale)
                }
            }
        }

        override fun onActivityStarted(activity: Activity) {}
        override fun onActivityResumed(activity: Activity) {}
        override fun onActivityPaused(activity: Activity) {}
        override fun onActivityStopped(activity: Activity) {}
        override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
        override fun onActivityDestroyed(activity: Activity) {}
    }

    /**
     * 设置语言信息
     *
     * 说明：
     * 该方法建议在attachBaseContext和onConfigurationChange中调用，attachBaseContext可以保证页面加载时修改语言信息，
     * 而onConfigurationChange则是为了对应横竖屏切换时系统更新Resource的问题
     *
     * @param context application context
     */
    fun setConfiguration(context: Context?) {
        if (context == null) {
            return
        }
        /*
         * 为防止传入非ApplicationContext，这里做一次强制转化，目的是避免onConfigurationChange可能导致的问题，
         * 因为onConfigurationChange被触发时系统会更新ApplicationContext中的Resource，如果页面包含Runtime资源
         * （运行时动态加载的资源）时，有可能语言显示不一致。
         */
        val appContext = context.applicationContext
        val preferredLocale = sysPreferredLocale
        val configuration = appContext.resources.configuration
        if (Build.VERSION.SDK_INT >= 17) {
            configuration.setLocale(preferredLocale)
        } else {
            configuration.locale = preferredLocale
        }
        // 更新context中的语言设置
        val resources = appContext.resources
        val dm = resources.displayMetrics
        resources.updateConfiguration(configuration, dm)
    }

    val sysPreferredLocale: Locale
        /**
         * 获取系统首选语言
         *
         * 注意：该方法获取的是用户实际设置的不经API调整的系统首选语言
         *
         * @return
         */
        get() {
            val locale: Locale
            //7.0以下直接获取系统默认语言
            locale = if (Build.VERSION.SDK_INT < 24) {
                // 等同于context.getResources().getConfiguration().locale;
                Locale.getDefault()
                // 7.0以上获取系统首选语言
            } else {
                /*
             * 以下两种方法等价，都是获取经API调整过的系统语言列表（可能与用户实际设置的不同）
             * 1.context.getResources().getConfiguration().getLocales()
             * 2.LocaleList.getAdjustedDefault()
             */
                // 获取用户实际设置的语言列表
                LocaleList.getDefault()[0]
            }
            return locale
        }
}